﻿using System;

namespace Xenta.Utils
{
    /// <summary>
    /// Represents the flag enums helper.
    /// </summary>
    public static class FlagsHelper
    {
        #region Constants


        /*       
         *        0               1               2               3              
         * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         * |0|             O               |     G2    |     G1    |   S   |
         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        */

        /// <summary>
        /// 31 bits(0x7fffffff)
        /// </summary>
        public const int FLAG_MASK = 0x7fffffff;

        /// <summary>
        /// 4 bits(0x0000000f)
        /// </summary>
        public const int FLAG_MASK_S = 0x0000000f;

        /// <summary>
        /// 6 bits(0x000003f0)
        /// </summary>
        public const int FLAG_MASK_G1 = 0x000003f0;

        /// <summary>
        /// 6 bits(0x0000fc00)
        /// </summary>
        public const int FLAG_MASK_G2 = 0x0000fc00;

        /// <summary>
        /// 15 bits(0x7fff0000)
        /// </summary>
        public const int FLAG_MASK_O = 0x7fff0000;

        #endregion

        #region Methods

        /// <summary>
        /// Gets the S part of the flags.
        /// </summary>
        /// <typeparam name="TEnum">The enum type.</typeparam>
        /// <param name="value">The enum value.</param>
        /// <returns>The part value.</returns>
        public static TEnum S_Flags<TEnum>(TEnum value)
            where TEnum : struct, IConvertible
        {
            return EnumHelper.And(value, FLAG_MASK_S);
        }

        /// <summary>
        /// Gets the G1 part of the flags.
        /// </summary>
        /// <typeparam name="TEnum">The enum type.</typeparam>
        /// <param name="value">The enum value.</param>
        /// <returns>The part value.</returns>
        public static TEnum G1_Flags<TEnum>(TEnum value)
            where TEnum : struct, IConvertible
        {
            return EnumHelper.And(value, FLAG_MASK_G1);
        }

        /// <summary>
        /// Gets the G1 part of the flags.
        /// </summary>
        /// <typeparam name="TEnum">The enum type.</typeparam>
        /// <param name="value">The enum value.</param>
        /// <returns>The part value.</returns>
        public static TEnum G2_Flags<TEnum>(TEnum value)
            where TEnum : struct, IConvertible
        {
            return EnumHelper.And(value, FLAG_MASK_G2);
        }

        /// <summary>
        /// Gets the O part of the flags.
        /// </summary>
        /// <typeparam name="TEnum">The enum type.</typeparam>
        /// <param name="value">The enum value.</param>
        /// <returns>The part value.</returns>
        public static TEnum O_Flags<TEnum>(TEnum value)
            where TEnum : struct, IConvertible
        {
            return EnumHelper.And(value, FLAG_MASK_O);
        }

        #endregion
    }
}
